﻿
using System;
using System.Collections.Generic;
using System.Threading;
using System.Windows.Forms;
using DataTools.Interop;

namespace DataTools.Monitoring {

    /// <summary>
    /// Identifies the kind of place the failure originated.
    /// </summary>
    internal enum FailOrigins : uint {
        
        /// <summary>
        /// Failure in a watcher.
        /// </summary>
        Watcher,

        /// <summary>
        /// Failure in an imager.
        /// </summary>
        Imager
    };

    internal struct FAIL_STRUCT
    {
        /// <summary>
        /// The internally assigned fail id.
        /// </summary>
        /// <remarks></remarks>
        public System.Guid FailId;

        /// <summary>
        /// The specific failure code.
        /// </summary>
        /// <remarks></remarks>
        public int FailCode;

        /// <summary>
        /// A string identifier of the origin of the failure
        /// </summary>
        /// <remarks></remarks>
        public string Origin;

        /// <summary>
        /// The origin task of the failure in question
        /// </summary>
        /// <remarks></remarks>
        public FailOrigins OriginType;

        /// <summary>
        /// Any pertinent information will be here
        /// </summary>
        /// <remarks></remarks>
        public object Buffer;
    }

    internal class FailDispatch
    {
        public delegate void FailOccurredEvent(FAIL_STRUCT fail);
        public static event FailOccurredEvent FailOccurred;

        protected static void OnFailOccurred(FAIL_STRUCT fail) {
            if (FailOccurred != null) {
                FailOccurred(fail);
            }
        }

        public static void AlertFail(ref FAIL_STRUCT fail) 
        {

            fail.FailId = Guid.NewGuid();
            FAIL_STRUCT fnew = fail;

            var th = new Thread( 
                () => {
                        OnFailOccurred(fnew);
                });

            th.SetApartmentState(ApartmentState.STA);
            th.Start();

            LogFailEvent(fail);
        }

        public static void LogFailEvent(FAIL_STRUCT fail)
        {
            // code to log goes here.
        }

    }

    internal class MonitorDispatch
    {
        public static List<FSMonitor> Monitors = new List<FSMonitor>();

        public static bool Create(FSMonitor wnd, IntPtr hwndOwner) 
        {
            var cp = new CreateParams();

            if (hwndOwner != IntPtr.Zero)
            {
                cp.Style = (int)WndConst.WS_CHILDWINDOW;
                cp.Parent = hwndOwner;
            }
        
            wnd.CreateHandle(cp);

            if (wnd.Handle != IntPtr.Zero)
            {
                Monitors.Add(wnd);
                return true;
            }
        
            return false;
        }

        public static void Add(FSMonitor wnd)
        {
            Monitors.Add(wnd);
        }

        public static void Remove(FSMonitor wnd)
        {
            Monitors.Remove(wnd);
        }

    }

}